package com.jz.digital.utils;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @author jiangm
 * @date 2021/1/5 18:17
 * @Description:
 */
public class FileDialDefinedUtil {
    private static final String TAG = "FileDialDefinedUtil";
    // 固件设备的json文件名称
    public static final String DEVICE_JSON = "iwf.json";
    // APP端的json文件名称
    public static final String APP_JSON = "app.json";
    // 文件名称压缩包
    public static final String FILE_ZIP = ".zip";

    // 保存zip路径
    public static final String SAVEZIP_DIR = "/Veryfit" + File.separator +
            "/dialdefined" + File.separator +
            "/zip" + File.separator;
    // 自定义表盘编辑文件夹
    public static final String FILEDIR_NAME = "watchFile";
    // 自定义表盘编辑文件夹
    public static final String FILEDIR_NAME_FUNCTION = "watchFileFunction";
    // 自定义表盘编辑文件夹
    public static final String STYLE_BG = "{style_bg}";
    // app图片文件夹
    public static final String APP_FILE = "app";
    // app图片文件夹
    public static final String APP_FILE_NEW = "images";

    // app 存放固件需要的图片文件夹
    public static final String APP_FILE_FIREWARE = "firmware_icons";
    // 压缩图片大小k
    public static final int IMAGE_SIZE = 25;


//    /**
//     * 自定义表盘生存图片宽
//     */
//    public static final int DEFINED_WALL_PAPER_WIDTH = 320;
//    /**
//     * 自定义表盘生存图片高
//     */
//    public static final int DEFINED_WALL_PAPER_HEIGHT = 360;


    /**
     * 获取zip文件解压后的大小
     *
     * @param filePath
     * @return
     */
    public static long getZipRealSize(String filePath) {
        long size = 0;
        if (TextUtils.isEmpty(filePath)) return size;
        ZipFile f=null;
        try {
            f = new ZipFile(filePath);
            Enumeration<? extends ZipEntry> en = f.entries();
            while (en.hasMoreElements()) {
                size += en.nextElement().getSize();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (f != null) {
                try {
                    f.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        }
        return size;
    }

    /**
     * 解压Zip文件
     *
     * @param desPath 解压目的地目录
     * @param zipFile zip文件名(包含去路径)
     * @return true 表示解压成功,false 表示解压失败.
     */
    public static boolean unpackZip(String desPath, String zipFile) {
        if (!zipFile.endsWith(".zip")) {
            return false;
        }
        File des = new File(desPath);
        if (!des.exists()) {
            des.mkdir();
        }
        InputStream is = null;
        ZipInputStream zis = null;
        FileOutputStream fout = null;
        try {
            String filename;
            is = new FileInputStream(zipFile);
            zis = new ZipInputStream(new BufferedInputStream(is));
            ZipEntry ze;
            byte[] buffer = new byte[1024];
            int count;

            while ((ze = zis.getNextEntry()) != null) {
                String zeName = ze.getName().replace("../", "");
                if (zeName.contains(File.separator)) {
                    filename = zeName.substring(zeName.indexOf(File.separator) + 1);
                } else {
                    filename = zeName;
                }

                // Need to create directories if not exists, or
                // it will generate an Exception...
                if (ze.isDirectory()) {
                    File fmd = new File(desPath + ze);
                    fmd.mkdirs();
                    continue;
                }

                fout = new FileOutputStream(desPath + zeName);

                while ((count = zis.read(buffer)) != -1) {
                    fout.write(buffer, 0, count);
                }

                fout.close();
                zis.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            IOUtil.close(is);
            IOUtil.close(zis);
            IOUtil.close(fout);
        }

        return true;
    }

    /**
     * 解压Zip文件
     *
     * @param desPath 解压目的地目录
     * @param zipFile zip文件名(包含去路径)
     * @return true 表示解压成功,false 表示解压失败.
     * modify: google play console 提示的zip路径遍历漏洞修复,去除zipEntry.getName中的”../“
     */
    public static boolean unpackCopyZip(String desPath, String zipFile) {
        if (!zipFile.endsWith(".zip")) {
            return false;
        }
        File des = new File(desPath);
        if (!des.exists()) {
            des.mkdirs();
        }
        InputStream is = null;
        ZipInputStream zis = null;
        FileOutputStream fout = null;
        try {
            String filename;
            is = new FileInputStream(zipFile);
            zis = new ZipInputStream(new BufferedInputStream(is));
            ZipEntry ze;
            byte[] buffer = new byte[1024];
            int count;

            while ((ze = zis.getNextEntry()) != null) {
                String zeName = ze.getName().replace("../", "");
                if (zeName.contains(File.separator)) {
                    filename = zeName.substring(0, zeName.lastIndexOf(File.separator));
                    File file = new File(desPath + File.separator + filename);
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                } else {
                    filename = zeName;
                }

                // Need to create directories if not exists, or
                // it will generate an Exception...
                if (ze.isDirectory()) {
                    File fmd = new File(desPath + ze);
                    fmd.mkdirs();
                    continue;
                }

                fout = new FileOutputStream(desPath + zeName);

                while ((count = zis.read(buffer)) != -1) {
                    fout.write(buffer, 0, count);
                }

                fout.close();
                zis.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            IOUtil.close(is);
            IOUtil.close(zis);
            IOUtil.close(fout);
        }

        return true;
    }

    /**
     * 解压Zip文件
     *
     * @param desPath 解压目的地目录
     * @param zipFile zip文件名(包含去路径)
     * @return true 表示解压成功,false 表示解压失败.
     */
    public static boolean unpackCopyZip(String desPath, String desName, String zipFile) {
        if (!zipFile.endsWith(".zip")) {
            return false;
        }
        File des = new File(desPath);
        if (!des.exists()) {
            des.mkdir();
        }
        InputStream is = null;
        ZipInputStream zis = null;
        FileOutputStream fout = null;
        try {
            String filename;
            is = new FileInputStream(zipFile);
            zis = new ZipInputStream(new BufferedInputStream(is));
            ZipEntry ze;
            byte[] buffer = new byte[1024];
            int count;

            while ((ze = zis.getNextEntry()) != null) {
                String zeName = ze.getName().replace("../", "");
                if (zeName.contains(File.separator)) {
                    filename = zeName.substring(0, zeName.lastIndexOf(File.separator));
                    File file = new File(desPath + File.separator + filename);
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                } else {
                    filename = zeName;
                }

                // Need to create directories if not exists, or
                // it will generate an Exception...
                if (ze.isDirectory()) {
                    File fmd = new File(desPath + ze);
                    fmd.mkdirs();
                    continue;
                }

                fout = new FileOutputStream(desPath + zeName);

                while ((count = zis.read(buffer)) != -1) {
                    fout.write(buffer, 0, count);
                }

                fout.close();
                zis.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            IOUtil.close(is);
            IOUtil.close(zis);
            IOUtil.close(fout);
        }

        return true;
    }


    public static boolean checkFileExist(String path, String name) {
        File file = new File(path);
        String[] files = file.list();
        if (files == null || files.length == 0)
            return false;
        for (int i = 0; i < files.length; i++) {
            String filename = files[i];
            if (files[i].contains(".")) {
                filename = files[i].substring(0, files[i].lastIndexOf("."));
            }
            if (TextUtils.equals(filename, name)) {
                return true;
            }
        }
        return false;
    }

    // 写入文件
    public static String getWriteDir(int deviceId) {
        return "/Veryfit" + File.separator +
                "/dialdefined" + File.separator +
                "/" + deviceId + File.separator;
    }

    // 保存zip路径
    public static String getReadDir(int deviceId) {
        return "/Veryfit" + "/dialdefined" + "/" + deviceId + "/";
    }

    public static String unZipDir(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getWriteDir(deviceId);
    }

    public static String zipDir(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getReadDir(deviceId);
    }

    public static String copeFileDir(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getReadDir(deviceId) + FILEDIR_NAME + "/";
    }

    public static String jsonDir(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getWriteDir(deviceId) +
                FILEDIR_NAME;
    }

    public static String appFilePng(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getWriteDir(deviceId) +
                FILEDIR_NAME + File.separator + APP_FILE;
    }

    public static String jsonDirNew(Context context, int deviceId) {
        return context.getFilesDir().getPath() + getWriteDir(deviceId) +
                FILEDIR_NAME_FUNCTION;
    }

    /**
     * 新的自定义表盘解压路径
     *
     * @param context
     * @param deviceId
     * @param dialName
     * @return
     */
    public static String jsonDirFunction(Context context, int deviceId, String dialName) {
        return context.getFilesDir().getPath() + getWriteDir(deviceId) +
                FILEDIR_NAME_FUNCTION + File.separator + dialName;
    }

    public static String appFilePngFunction(Context context, int deviceId, String dialName) {
        return jsonDirFunction(context, deviceId, dialName) + File.separator + APP_FILE_NEW;
    }

    public static String jsonDirFunctionAppFile(Context context, int deviceId, String dialName) {
        return jsonDirFunction(context, deviceId, dialName) + File.separator + APP_JSON;
    }

    public static String appFireWareIcons(Context context, int deviceId, String dialName) {
        return appFilePngFunction(context, deviceId, dialName) + File.separator + APP_FILE_FIREWARE;
    }

    /**
     * 固件需要的包目录
     *
     * @param context
     * @param deviceId
     * @param name
     * @return
     */
    public static String firewareFunctionDir(Context context, int deviceId, String name) {
        return jsonDirFunction(context, deviceId, name) + File.separator + name;
    }

    /**
     * 固件需要的包目录
     *
     * @param context
     * @param deviceId
     * @param name
     * @return
     */
    public static String firewareFunctionZip(Context context, int deviceId, String name) {
        return jsonDirFunction(context, deviceId, name) + File.separator + name + FILE_ZIP;
    }

    public static String fileDir(Context context, int deviceId) {
        return context.getFilesDir().getPath() +
                getReadDir(deviceId) +
                FILEDIR_NAME;
    }

    public static String saveZipDir(Context context) {
        return context.getFilesDir().getPath() +
                SAVEZIP_DIR;
    }


    /**
     * @param filePath 文件路径
     * @return file存在则删除
     */
    public static void removeFile(String filePath) {
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
    }

    /**
     * @throws Exception srcfilrString  /data/user/0/com.watch.life/files/Veryfit//dialdefined//336/watchFile/
     *                   zipfileString /data/user/0/com.watch.life/files/Veryfit/dialdefined/336/zzp.zip
     */
    public static void zipDialFolder(String srcFileString, String zipFileString, ArrayList<String> dialList) {
        Log.v("XZip", "srcFileString=" + srcFileString + " zipFileString=" + zipFileString);
        try {
            ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString));

            File file = new File(srcFileString);

            zipDialFiles(file.getParent() + File.separator + file.getName(), "", outZip, dialList);
            outZip.finish();
            outZip.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        this.zip.onFinish();
//        this.zip.onFinish();
    }

    /**
     * @param folderString
     * @param fileString
     * @param zipOutputSteam
     * @throws Exception
     */
    private static void zipDialFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam, ArrayList<String> dialList) {
        Log.v("XZip", "folderString=" + folderString + " fileString=" + fileString);


        if (zipOutputSteam == null)
            return;
        try {

            File file = new File(folderString + File.separator + fileString);
            boolean isZipFile = false;
            for (int i = 0; i < dialList.size(); i++) {
                if (file.getName().equals(dialList.get(i))) {
                    isZipFile = true;
                    break;
                }
            }
            if (file.isFile()) {
                if (!isZipFile) {
                    ZipEntry zipEntry = new ZipEntry(fileString);
                    FileInputStream inputStream = new FileInputStream(file);
                    zipOutputSteam.putNextEntry(zipEntry);

                    int len;
                    byte[] buffer = new byte[4096];
                    while ((len = inputStream.read(buffer)) != -1) {
                        try {
                            zipOutputSteam.write(buffer, 0, len);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                    zipOutputSteam.closeEntry();
                }
            } else {

                String[] fileList = file.list();
                if (fileList == null) return;
                if (fileList.length <= 0) {
                    ZipEntry zipEntry = new ZipEntry(fileString + File.separator);
                    zipOutputSteam.putNextEntry(zipEntry);
                    zipOutputSteam.closeEntry();
                }

                for (int i = 0; i < fileList.length; i++) {
                    boolean isZipDir = false;
                    for (int j = 0; j < dialList.size(); j++) {
                        if (file.getName().equals(dialList.get(j))) {
                            isZipDir = true;
                            break;
                        }
                    }
                    if (isZipDir) {
                        continue;
                    }
                    if (TextUtils.isEmpty(fileString)) {
                        zipDialFiles(folderString, fileList[i], zipOutputSteam, dialList);
                    } else {
                        zipDialFiles(folderString, fileString + File.separator + fileList[i], zipOutputSteam, dialList);
                    }
                }// run_go of for

            }// run_go of if
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * @param folderString
     * @param fileString
     * @param zipOutputSteam
     * @throws Exception
     */
    private static void ZipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) throws Exception {
        Log.v("XZip", "ZipFiles(String, String, ZipOutputStream)");

        if (zipOutputSteam == null)
            return;

        File file = new File(folderString + fileString);

        if (file.isFile()) {

            ZipEntry zipEntry = new ZipEntry(fileString);
            FileInputStream inputStream = new FileInputStream(file);
            zipOutputSteam.putNextEntry(zipEntry);

            int len;
            byte[] buffer = new byte[4096];
            while ((len = inputStream.read(buffer)) != -1) {
                zipOutputSteam.write(buffer, 0, len);
            }

            zipOutputSteam.closeEntry();
        } else {

            String[] fileList = file.list();

            if (fileList.length <= 0) {
                ZipEntry zipEntry = new ZipEntry(fileString + File.separator);
                zipOutputSteam.putNextEntry(zipEntry);
                zipOutputSteam.closeEntry();
            }

            for (int i = 0; i < fileList.length; i++) {
                ZipFiles(folderString, fileList[i], zipOutputSteam);
            }// run_go of for

        }// run_go of if

    }

    /**
     * 复制文件夹及其中的文件
     *
     * @param oldPath String 原文件夹路径 如：data/user/0/com.test/files
     * @param newPath String 复制后的路径 如：data/user/0/com.test/cache
     * @return <code>true</code> if and only if the directory and files were copied;
     * <code>false</code> otherwise
     */
    public static boolean copyFolder(String oldPath, String newPath) {
        try {
            File newFile = new File(newPath);
            if (!newFile.exists()) {
                if (!newFile.mkdirs()) {
                    Log.e("--Method--", "copyFolder: cannot create directory.");
                    return false;
                }
            }
            File oldFile = new File(oldPath);
            String[] files = oldFile.list();
            File temp;
            for (String file : files) {
                if (oldPath.endsWith(File.separator)) {
                    temp = new File(oldPath + file);
                } else {
                    temp = new File(oldPath + File.separator + file);
                }

                if (temp.isDirectory()) {   //如果是子文件夹
                    copyFolder(oldPath + "/" + file, newPath + "/" + file);
                } else if (!temp.exists()) {
                    Log.e("--Method--", "copyFolder:  oldFile not exist.");
                    return false;
                } else if (!temp.isFile()) {
                    Log.e("--Method--", "copyFolder:  oldFile not file.");
                    return false;
                } else if (!temp.canRead()) {
                    Log.e("--Method--", "copyFolder:  oldFile cannot read.");
                    return false;
                } else {
                    FileInputStream fileInputStream = new FileInputStream(temp);
                    FileOutputStream fileOutputStream = new FileOutputStream(newPath + "/" + temp.getName());
                    byte[] buffer = new byte[1024];
                    int byteRead;
                    while ((byteRead = fileInputStream.read(buffer)) != -1) {
                        fileOutputStream.write(buffer, 0, byteRead);
                    }
                    fileInputStream.close();
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }

            /* 如果不需要打log，可以使用下面的语句
            if (temp.isDirectory()) {   //如果是子文件夹
                copyFolder(oldPath + "/" + file, newPath + "/" + file);
            } else if (temp.exists() && temp.isFile() && temp.canRead()) {
                FileInputStream fileInputStream = new FileInputStream(temp);
                FileOutputStream fileOutputStream = new FileOutputStream(newPath + "/" + temp.getName());
                byte[] buffer = new byte[1024];
                int byteRead;
                while ((byteRead = fileInputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, byteRead);
                }
                fileInputStream.close();
                fileOutputStream.flush();
                fileOutputStream.close();
            }
            */
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 文件拷贝
     *
     * @param fromFilePath
     * @param toFilePath
     */
    public static void copyFile(String fromFilePath, String toFilePath) {
        File toFile = new File(toFilePath);
        FileInputStream fis = null;
        FileOutputStream bos = null;
        try {
            if (!toFile.exists()) {
                File parens = new File(toFile.getParent());
                parens.mkdirs();
            }
            byte[] bytes = new byte[1024];
            int len = 0;
            fis = new FileInputStream(fromFilePath);
            bos = new FileOutputStream(toFilePath);
            while ((len = fis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            bos.close();
            fis.close();
        } catch (Exception e) {

        } finally {
            if (bos != null) {
                try {
                    bos.flush();
                    bos.close();
                } catch (Exception e) {
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (Exception e) {
                }
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static void deleteFile(String fileName) {
        File file = new File(fileName);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            file.delete();
        }
    }

    public static void deleteDirectory(String dir) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            return;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                deleteFile(files[i].getAbsolutePath());

            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                deleteDirectory(files[i]
                        .getAbsolutePath());

            }
        }
        // 删除当前目录
        dirFile.delete();
    }
    /**
     * 删除目录+过滤文件
     * @param dir
     * @param filterName 筛选名称
     */
    public static void deleteDirectory(String dir,String filterName) {
        // 如果dir不以文件分隔符结尾，自动添加文件分隔符
        if (!dir.endsWith(File.separator))
            dir = dir + File.separator;
        File dirFile = new File(dir);
        if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
            return;
        }
        boolean flag = true;
        // 删除文件夹中的所有文件包括子目录
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            // 删除子文件
            if (files[i].isFile()) {
                File file = files[i];
                String fileName = file.getName();
                // 需要过滤的文件不为空并且文件名称包含需要过滤的字段直接跳过不删除
                if (!TextUtils.isEmpty(filterName)&&fileName.contains(filterName)){
                    continue;
                }
                deleteFile(file.getAbsolutePath());

            }
            // 删除子目录
            else if (files[i].isDirectory()) {
                deleteDirectory(files[i]
                        .getAbsolutePath());

            }
        }
        // 删除当前目录
        dirFile.delete();
    }
}
